package com.flyqiu.flow.api.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyqiu.common.tools.FlyQiuCollectionTools;
import com.flyqiu.flow.model.business.BaseFlyBusiness;
import com.flyqiu.flow.model.business.DefaultBaseFlyBusiness;
import com.flyqiu.flow.api.context.ProcInstContext;
import com.flyqiu.flow.common.std.IProIcActivityMove;
import com.flyqiu.flow.model.entity.ru.ProcRuActivity;
import com.flyqiu.flow.model.entity.ru.ProcRuInst;

import java.util.List;

/**
 * 流程实例服务
 */
public interface FlowRunningService {

    /**
     * 启动流程
     *
     * @param procDeployDefId 流程发布定义id
     * @return 流程实例
     */
    default ProcRuInst start(String procDeployDefId) {
        return start(procDeployDefId, null);
    }

    /**
     * 启动流程
     *
     * @param procDeployDefId 流程发布定义id
     * @param procVariable    流程变量
     * @return 流程实例
     */
    default ProcRuInst start(String procDeployDefId, JSONObject procVariable) {
        return start(procDeployDefId, procVariable, new DefaultBaseFlyBusiness(null, null, null));
    }

    /**
     * 启动流程
     *
     * @param procDeployDefId 流程发布定义id
     * @param procVariable    流程变量
     * @param businessKey     流程业务key
     * @return 流程实例
     */
    default ProcRuInst start(String procDeployDefId, JSONObject procVariable, String businessKey) {
        return start(procDeployDefId, procVariable, new DefaultBaseFlyBusiness(null, businessKey, null));
    }

    /**
     * 启动流程
     *
     * @param procDeployDefId 流程部署定义id
     * @param procVariable    流程变量
     * @param business        业务信息
     * @return {@link ProcRuInst} 流程实例信息
     */
    ProcRuInst start(String procDeployDefId, JSONObject procVariable, BaseFlyBusiness business);

    /**
     * 根据流程定义key 或者流程模型key启动流程
     *
     * @param procDefKey 流程定义key
     * @return 流程实例
     */
    default ProcRuInst startByProcDefKey(String procDefKey) {
        return startByProcDefKey(procDefKey, null);
    }

    /**
     * 根据流程定义key 或者流程模型key启动流程
     *
     * @param procDefKey   流程定义key
     * @param procVariable 流程变量
     * @return 流程实例
     */
    default ProcRuInst startByProcDefKey(String procDefKey, JSONObject procVariable) {
        return startByProcDefKey(procDefKey, procVariable, new DefaultBaseFlyBusiness(null, null, null));
    }

    /**
     * 根据流程定义key 或者流程模型key启动流程
     *
     * @param procDefKey   流程定义key
     * @param procVariable 流程比哪里
     * @param businessKey  流程业务key
     * @return {@link ProcRuInst} 流程实例信息
     */
    default ProcRuInst startByProcDefKey(String procDefKey, JSONObject procVariable, String businessKey) {
        return startByProcDefKey(procDefKey, procVariable, businessKey, null);
    }

    /**
     * 根据流程定义key 或者流程模型key启动流程
     *
     * @param procDefKey   流程定义key
     * @param procVariable 流程比哪里
     * @param businessKey  流程业务key
     * @param businessId   流程业务id
     * @return {@link ProcRuInst} 流程实例信息
     */
    default ProcRuInst startByProcDefKey(String procDefKey, JSONObject procVariable, String businessKey, String businessId) {
        DefaultBaseFlyBusiness business = new DefaultBaseFlyBusiness(businessId, businessKey, null);
        return startByProcDefKey(procDefKey, procVariable, business);
    }

    /**
     * 根据流程定义key 或者流程模型key启动流程
     *
     * @param procDefKey   流程定义key
     * @param procVariable 流程比哪里
     * @param business     流程业务
     * @return {@link ProcRuInst} 流程实例信息
     */
    ProcRuInst startByProcDefKey(String procDefKey, JSONObject procVariable, BaseFlyBusiness business);


    /**
     * 分页查询流程实例
     *
     * @param page    分页信息
     * @param wrapper 查询条件
     * @return 运行中流程实例分页
     */
    Page<ProcRuInst> pageProcInst(Page<ProcRuInst> page, Wrapper<ProcRuInst> wrapper);


    /**
     * 流程查询
     *
     * @param wrapper 查询条件
     * @return 流程实例
     */
    List<ProcRuInst> listProcInst(Wrapper<ProcRuInst> wrapper);

    /**
     * 获取流程实例
     *
     * @param wrapper 查询条件
     * @return 流程实例
     */
    default ProcRuInst getProcInst(Wrapper<ProcRuInst> wrapper) {
        List<ProcRuInst> procRuInsts = listProcInst(wrapper);
        if (FlyQiuCollectionTools.isEmpty(procRuInsts)) return null;
        if (procRuInsts.size() > 2) {
            throw new RuntimeException("Multiple process instances found");
        }
        return procRuInsts.get(0);
    }

    /**
     * 根据流程实例id获取流程运行时上下文
     *
     * @param procInstId 流程实例id
     * @return 流程运行时上下文
     */
    ProcInstContext getProcRuntimeContext(String procInstId);

    /**
     * 流程实例查询
     *
     * @param procInstId 流程实例id
     * @return 流程实例
     */
    default ProcRuInst getProcInstByInstId(String procInstId) {
        LambdaQueryWrapper<ProcRuInst> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProcRuInst::getId, procInstId);
        return selectOneProcInst(wrapper);
    }

    /**
     * 流程实例查询
     *
     * @param wrapper 查询条件
     * @return 流程实例
     */
    ProcRuInst selectOneProcInst(Wrapper<ProcRuInst> wrapper);

    /**
     * 流程实例查询
     *
     * @param wrapper 查询条件
     * @return 流程数量
     */
    long countProcInst(Wrapper<ProcRuInst> wrapper);


    /**
     * 删除流程实例
     *
     * @param procInstId 流程实例id
     */
    default void deleteProcInst(String procInstId) {
        deleteProcInst(procInstId, null);
    }

    /**
     * 删除原因
     *
     * @param procInstId 流程实例id
     * @param reason     删除原因
     */
    default void deleteProcInst(String procInstId, String reason) {
        deleteProcInst(procInstId, null, reason);
    }

    /**
     * @param procInstId 流程实例id
     * @param params     其他扩展参数
     * @param reason     删除原因
     */
    void deleteProcInst(String procInstId, JSONObject params, String reason);

    /**
     * 分页查询活动
     *
     * @param page         分页信息
     * @param queryWrapper 查询条件
     * @return 活动信息分页
     */
    Page<ProcRuActivity> pageActivity(Page<ProcRuActivity> page, LambdaQueryWrapper<ProcRuActivity> queryWrapper);

    /**
     * 查询活动
     *
     * @param queryWrapper 查询条件
     * @return 活动信息
     */
    List<ProcRuActivity> listActivity(LambdaQueryWrapper<ProcRuActivity> queryWrapper);

    /**
     * @param queryWrapper 查询条件
     * @return 活动数量
     */
    long countActivity(LambdaQueryWrapper<ProcRuActivity> queryWrapper);

    /**
     * 查询活动信息
     *
     * @param activityId 活动id
     * @return {@link ProcRuActivity} 活动信息
     */
    ProcRuActivity getActivity(String activityId);

    /**
     * 活动移动到目标位置
     *
     * @param activityId   当前活动id
     * @param targetDefKey 目标定义key
     * @return {@link ProcRuActivity} 活动信息
     */
    List<ProcRuActivity> activityMoveTo(String activityId, String targetDefKey);

    /**
     * 活动移动到目标位置
     *
     * @param activityId   活动id
     * @param targetDefKey 目标定义key
     * @param move         移动策略执行器
     * @return {@link ProcRuActivity} 活动信息
     */

    List<ProcRuActivity> activityMoveTo(String activityId, String targetDefKey, IProIcActivityMove move);


}
